﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ObviousCode.UI.Aspect.DevHack;
using System.Reflection;
using ObviousCode.UI.Aspect.PluginLibrary.Interfaces;
using ObviousCode.Aspect.PluginLibrary.Interfaces;
using ObviousCode.UI.Aspect.ConfigHandler;
using System.Configuration;
using ObviousCode.UI.Aspect.ConfigHandler.ConfigurationSectionObjects;

namespace ObviousCode.UI.Aspect.Plugins
{
    internal class PluginLoader
    {
        public static IEnumerable<ISurfaceObjectFactory> LoadPluginsFromAppConfig(IAspectDesigner host)
        {            
            //Read from app config
            SurfaceObjectPluginAssemblyNames plugins = (SurfaceObjectPluginAssemblyNames)ConfigurationManager.GetSection("SurfaceObjectPluginAssemblyNames");

            if (plugins == null) yield break;

            foreach (SurfaceObjectPlugin plugin in plugins.Plugins)
            {
                string assemblyName = plugin.Name;
                Assembly assembly = Assembly.Load(assemblyName);

                if (!AssemblyContainsObjectPlugins(assembly))
                {
                    string message = "Assembly \"{0}\" does not contain ISurfaceObject Plugins";
                    DummyLog.Log(message, assemblyName);

                    continue;
                }

                foreach(ISurfaceObjectFactory factory in GetPluginsByAssembly(assembly, host))
                {
                    factory.Setup();
                    yield return factory;
                }
            }
        }

        internal static IEnumerable<ISurfaceRelationshipFactory> LoadRelationshipPluginsFromAppConfig(IAspectDesigner host)
        {
            //Read from app config
            SurfaceRelationshipPluginAssemblyNames plugins = (SurfaceRelationshipPluginAssemblyNames)ConfigurationManager.GetSection("SurfaceRelationshipPluginAssemblyNames");

            if (plugins == null) yield break;

            foreach (SurfaceRelationshipPlugin plugin in plugins.Plugins)
            {
                string assemblyName = plugin.Name;

                Assembly assembly = Assembly.Load(assemblyName);

                if (!AssemblyContainsRelationshipPlugins(assembly))
                {
                    string message = "Assembly \"{0}\" does not contain ISurfaceRelationship Plugins";
                    DummyLog.Log(message, assemblyName);

                    continue;
                }

                foreach (ISurfaceRelationshipFactory factory in GetRelationshipPluginsByAssembly(assembly, host))
                {
                    factory.Setup();
                    yield return factory;
                }
            }
        }
        
        private static IEnumerable<ISurfaceObjectFactory> GetPluginsByAssembly(Assembly assembly, IAspectDesigner host)
        {
            foreach (Type type in assembly.GetTypes())
            {
                if (typeof(ISurfaceObjectFactory).IsAssignableFrom(type))
                {
                    yield return (ISurfaceObjectFactory)Activator.CreateInstance(type, host);
                }
            }
        }

        private static IEnumerable<ISurfaceRelationshipFactory> GetRelationshipPluginsByAssembly(Assembly assembly, IAspectDesigner host)
        {
            foreach (Type type in assembly.GetTypes())
            {
                if (typeof(ISurfaceRelationshipFactory).IsAssignableFrom(type))
                {
                    yield return (ISurfaceRelationshipFactory)Activator.CreateInstance(type);
                }
            }
        }

        private static bool AssemblyContainsObjectPlugins(Assembly assembly)
        {
            //Better way of doing this?
            foreach (Type type in assembly.GetTypes())
            {
                if (typeof(ISurfaceObjectFactory).IsAssignableFrom(type))
                {
                    return true;
                }
            }

            return false;
        }

        private static bool AssemblyContainsRelationshipPlugins(Assembly assembly)
        {
            foreach (Type type in assembly.GetTypes())
            {
                if (typeof(ISurfaceRelationshipFactory).IsAssignableFrom(type))
                {
                    return true;
                }
            }

            return false;
        }

    }
}
